Skip to content

fix: identical endpoint name conflicts - #1521

Draft
akurinnoy wants to merge 3 commits into
devfile:mainfrom
akurinnoy:identical-endpoint-name
Draft

akurinnoy wants to merge 3 commits into
devfile:mainfrom
akurinnoy:identical-endpoint-name

Conversation

@akurinnoy

@akurinnoy akurinnoy commented Oct 8, 2025 •

Copy link
Copy Markdown
Collaborator

What does this PR do?

Prevents discoverable endpoint Service conflicts using normalized endpoint names:

  • The webhook checks matching workspaces in the same namespace using a cache index; unchanged endpoint-name sets and pure removals skip conflict checks. Its role gains DevWorkspace get/list/watch access.
  • The routing controller rejects foreign Services and protects owned Service updates and cleanup. Solvers also reject duplicate normalized names and names reserved for the aggregate workspace Service.
  • Endpoint name normalization uses fewer allocations. TLS routing mounts each discoverable Service certificate at /var/serving-cert/<service-name>/, with valid volume names for long Service names.

Admission is best-effort. Service ownership checks during reconciliation protect against concurrent requests and conflicts from contributed endpoints. Three ADRs document the ownership, certificate, and index decisions.

What issues does this PR fix or reference?

Fixes eclipse-che/che#23231

Is it tested? How?

Automated coverage includes normalization, update gating, cache index lifecycle and copy isolation, Service ownership/cleanup, and TLS naming. Live-cluster/envtest and E2E verification remain pending.

Same-namespace conflict detection

Save this as workspace.yaml:

apiVersion: workspace.devfile.io/v1alpha2
kind: DevWorkspace
metadata:
  name: endpoint-test-1
spec:
  started: true
  routingClass: basic
  template:
    components:
      - name: postgresql
        container:
          image: quay.io/fedora/postgresql-12:latest
          endpoints:
            - name: postgresql
              targetPort: 5432
              exposure: internal
              protocol: tcp
              attributes:
                discoverable: true
          env:
            - name: POSTGRESQL_USER
              value: user
            - name: POSTGRESQL_PASSWORD
              value: pass
            - name: POSTGRESQL_ROOT_PASSWORD
              value: root
            - name: POSTGRESQL_DATABASE
              value: db

Create the first workspace, wait for readiness, then try the same endpoint in a second workspace:

oc create namespace test-namespace
oc apply -n test-namespace -f workspace.yaml
oc wait --for=condition=Ready dw/endpoint-test-1 -n test-namespace --timeout=300s
sed 's/name: endpoint-test-1/name: endpoint-test-2/' workspace.yaml | oc apply -n test-namespace -f -

Expected: admission rejects the second workspace with discoverable endpoint 'postgresql' is already in use by workspace 'endpoint-test-1'.

Cross-namespace isolation

The same endpoint name must work in another namespace:

oc create namespace test-namespace-2
oc apply -n test-namespace-2 -f workspace.yaml
oc wait --for=condition=Ready dw/endpoint-test-1 -n test-namespace-2 --timeout=300s
oc get svc postgresql -n test-namespace
oc get svc postgresql -n test-namespace-2

Also verify that enabling discoverability on a conflicting endpoint is rejected, foreign Services remain untouched when routing fails, and cluster-tls gives each discoverable Service a separate certificate mount.

Cleanup:

oc delete namespace test-namespace test-namespace-2

PR Checklist

  • E2E tests pass (when PR is ready, comment /test v8-devworkspace-operator-e2e, v8-che-happy-path to trigger)
    • v8-devworkspace-operator-e2e: DevWorkspace e2e test
    • v8-che-happy-path: Happy path for verification integration with Che

@akurinnoy akurinnoy self-assigned this Oct 8, 2025
Comment thread controllers/controller/devworkspacerouting/solvers/basic_solver.go Outdated
@akurinnoy
akurinnoy marked this pull request as draft October 8, 2025 14:26
Comment thread controllers/controller/devworkspacerouting/solvers/common.go Outdated
@openshift-ci openshift-ci Bot added the lgtm label Oct 9, 2025
@akurinnoy
akurinnoy marked this pull request as ready for review October 9, 2025 10:16
Comment thread webhook/workspace/handler/validate_test.go Outdated
Comment thread webhook/workspace/handler/validate_test.go Outdated
Comment thread webhook/workspace/handler/validate_test.go Outdated
Comment thread controllers/controller/devworkspacerouting/solvers/errors.go Outdated
@rohanKanojia

Copy link
Copy Markdown
Member

I tested the PR with abovementioned steps and it seems to work as expected ✔️

@akurinnoy

Copy link
Copy Markdown
Collaborator Author

/retest

// GetDiscoverableServicesForEndpoints converts the endpoint list into a set of services, each corresponding to a single discoverable
// endpoint from the list. Endpoints with the NoneEndpointExposure are ignored.
func GetDiscoverableServicesForEndpoints(endpoints map[string]controllerv1alpha1.EndpointList, meta DevWorkspaceMetadata) []corev1.Service {
func GetDiscoverableServicesForEndpoints(endpoints map[string]controllerv1alpha1.EndpointList, meta DevWorkspaceMetadata, cl client.Client, log logr.Logger) ([]corev1.Service, error) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@akurinnoy is there a reason for implementing duplicate endpiont detection in both the webhook and the GetDiscoverableServicesForEndpoints function?

@akurinnoy akurinnoy Nov 17, 2025 •

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While the webhook prevents the DevWorkspaces (which will cause endpoint conflicts) from being created, the controller checks other cases:

  • two workspaces created simultaneously - both of them may pass the webhook validation
  • services can be created from other sources
  • old workspaces, created before this validation

Is this the answer to your question?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Btw, while looking at this method, I noticed it’s also used in che-operator here:

che_routing.go

objs.Services = solvers.GetDiscoverableServicesForEndpoints(routing.Spec.Endpoints, workspaceMeta)

Just wanted to give a heads-up that we’ll likely need to update there as well.

@rohanKanojia

Copy link
Copy Markdown
Member

@akurinnoy : I ran your claude skill /ok-pr-review and it revealed this finding. Do you think it's a valid use case?

The webhook validation has a logic error that causes it to reject valid workspace creations. Currently, if the current workspace has a discoverable endpoint named X, and another workspace has any endpoint (discoverable OR NOT) named X, we reject it.

Steps to reproduce

  • Create workspace A with a non-discoverable endpoint named "postgresql"
oc create -f - <<EOF
apiVersion: workspace.devfile.io/v1alpha2
kind: DevWorkspace
metadata:
  name: workspace-a
  namespace: test-namespace
spec:
  started: true
  routingClass: basic
  template:
    components:
      - name: postgresql
        container:
          image: quay.io/fedora/postgresql-12:latest
          endpoints:
            - name: postgresql
              targetPort: 5432
              exposure: internal
              protocol: tcp
EOF
  • Create workspace B with a discoverable endpoint named "postgresql" (gets rejected)
oc create -f - <<EOF
apiVersion: workspace.devfile.io/v1alpha2
kind: DevWorkspace
metadata:
  name: workspace-b
  namespace: test-namespace
spec:
  started: true
  routingClass: basic
  template:
    components:
      - name: postgresql
        container:
          image: quay.io/fedora/postgresql-12:latest
          endpoints:
            - name: postgresql
              targetPort: 5432
              exposure: internal
              protocol: tcp
              attributes:
                discoverable: true
EOF

Do you think Workspace B should be allowed because Workspace A's endpoint is NOT discoverable and doesn't create a service named postgresql?

@tolusha

tolusha commented May 8, 2026

Copy link
Copy Markdown
Contributor

Hi! I'm che-ai-assistant — I help with your pull requests.

I check for new commands every 5m0s (if I am not busy :) ).

Available commands:

  • /che-ai-assistant generate-che-doc — Generate a documentation PR based on this PR's changes
  • /che-ai-assistant ok-pr-review — Run a comprehensive PR review (summary, code review, deep review, impact analysis)
  • /che-ai-assistant help — Show this help message

@akurinnoy
akurinnoy requested a review from btjd as a code owner May 14, 2026 15:08
@coderabbitai

coderabbitai Bot commented May 14, 2026 •

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR adds ownership-aware discoverable service handling: it introduces ServiceConflictError, refactors solvers to accept a Kubernetes client and logger and to perform in-cluster checks for existing Services, integrates conflict handling into the routing controller and admission webhook, and provides tests, RBAC, and test-suite config.

Changes

Discoverable Endpoint Conflict Detection

Layer / File(s) Summary
Error types and solver interface contracts
controllers/controller/devworkspacerouting/solvers/errors.go, controllers/controller/devworkspacerouting/solvers/solver.go
ServiceConflictError added with EndpointName and WorkspaceName. RoutingSolverGetter.GetSolver updated to accept logr.Logger.
Solver dependency injection: client and logger
controllers/controller/devworkspacerouting/solvers/basic_solver.go, controllers/controller/devworkspacerouting/solvers/cluster_solver.go
BasicSolver and ClusterSolver now store client.Client and logr.Logger; constructors NewBasicSolver and NewClusterSolver added; SolverGetter instantiates solvers via constructors.
Discoverable endpoint conflict detection in solvers
controllers/controller/devworkspacerouting/solvers/common.go, controllers/controller/devworkspacerouting/solvers/basic_solver.go, controllers/controller/devworkspacerouting/solvers/cluster_solver.go
DevWorkspaceMetadata gains DevWorkspaceName. GetDiscoverableServicesForEndpoints now accepts client.Client and logr.Logger, returns ([]corev1.Service, error), performs Get lookups for deterministic service names, detects ownership mismatches by DevWorkspaceIDLabel, and returns ServiceConflictError on conflict. Solvers call this function and propagate errors.
Controller reconciliation: conflict handling and error reporting
controllers/controller/devworkspacerouting/devworkspacerouting_controller.go
Controller passes reqLogger into GetSolver, includes DevWorkspaceName in workspace metadata, and explicitly handles *solvers.ServiceConflictError by logging and marking DevWorkspaceRouting as RoutingFailed.
Webhook admission validation for endpoint conflicts
webhook/workspace/handler/validate.go
ValidateDevfile invokes validateEndpoints, which collects discoverable endpoint names from the incoming DevWorkspace, lists DevWorkspaces in the same namespace, and returns solvers.ServiceConflictError on the first matching endpoint name found in another workspace; conflicts are aggregated into admission denial.
Tests, fixtures, RBAC and test config
controllers/controller/devworkspacerouting/solvers/common_test.go, webhook/workspace/handler/validate_test.go, webhook/workspace/handler/testdata/test-devworkspace.yaml, pkg/webhook/cluster_roles.go, controllers/workspace/suite_test.go, .gitignore
Adds unit tests covering discoverable service generation and conflict scenarios, webhook validateEndpoints tests, a test DevWorkspace manifest with a discoverable endpoint, RBAC rule allowing webhook to get,list,watch devworkspaces, disables metrics server in test manager, and ignores .claude/settings.local.json.

Sequence Diagram(s)

sequenceDiagram
  participant Webhook as Admission Webhook
  participant Controller as Routing Controller
  participant Solver as DevWorkspace Solver
  participant Client as Kubernetes API
  
  Webhook->>Webhook: validateEndpoints: collect discoverable endpoint names
  Webhook->>Client: list DevWorkspaces in namespace
  Client-->>Webhook: return workspace list
  Webhook->>Webhook: compare endpoint names across workspaces
  alt Conflict detected
    Webhook-->>Webhook: return ServiceConflictError
  else No conflict
    Webhook-->>Webhook: allow admission
  end
  
  Controller->>Solver: GetSolver with logger
  Solver->>Solver: NewBasicSolver/NewClusterSolver with client+logger
  Controller->>Solver: GetSpecObjects
  Solver->>Solver: GetDiscoverableServicesForEndpoints
  Solver->>Client: Get existing Service by name
  Client-->>Solver: Service or not-found
  alt Service exists and belongs to different workspace
    Solver-->>Solver: return ServiceConflictError
  else Service ok or not found
    Solver-->>Solver: create/update Service with ownership labels
  end
  alt Error returned
    Controller->>Controller: markRoutingFailed with conflict message
  else Success
    Controller->>Controller: continue reconciliation
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 3 | ❌ 1 | ❓ 1

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Out of Scope Changes check ❓ Inconclusive While most changes align with #23231, a potential logic issue was identified: validateEndpoints may incorrectly reject discoverable endpoints when a non-discoverable endpoint with the same name exists… Verify that validateEndpoints only checks for conflicts with discoverable endpoints and allows non-discoverable endpoints to coexist with discoverable ones having the same name.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed Title 'fix: identical endpoint name conflicts' is concise, specific, and accurately summarizes the main objective of the changeset.
Linked Issues check ✅ Passed The PR implements conflict detection and prevention for identically named endpoints at both controller and webhook levels, directly addressing the controller loop issue described in #23231.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Full details: Out of Scope Changes check

Explanation

While most changes align with #23231, a potential logic issue was identified: validateEndpoints may incorrectly reject discoverable endpoints when a non-discoverable endpoint with the same name exists in another workspace.

  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@controllers/controller/devworkspacerouting/devworkspacerouting_controller.go`:
- Around line 128-133: The code sets workspaceMeta.DevWorkspaceName =
instance.Name but must use the parent DevWorkspace's name from
instance.OwnerReferences; update the DevWorkspaceMetadata population so
DevWorkspaceName is assigned from the owner reference whose Kind (or
APIVersion+Kind) indicates the parent DevWorkspace (e.g., iterate
instance.OwnerReferences, find ownerRef.Kind == "DevWorkspace" and use
ownerRef.Name), and fall back to instance.Name only if no such ownerRef exists;
change the assignment near workspaceMeta (DevWorkspaceMetadata,
workspaceMeta.DevWorkspaceName) to use that ownerRef-derived name.

In `@controllers/controller/devworkspacerouting/solvers/common_test.go`:
- Around line 16-27: Reorder the import block in common_test.go into three
groups with blank lines between them: (1) standard library (e.g., "testing"),
(2) third-party and Kubernetes packages (e.g.,
"github.com/stretchr/testify/assert", "k8s.io/api/core/v1" as corev1,
"k8s.io/apimachinery/pkg/apis/meta/v1" as metav1,
"k8s.io/apimachinery/pkg/runtime",
"sigs.k8s.io/controller-runtime/pkg/client/fake",
"sigs.k8s.io/controller-runtime/pkg/log/zap"), and (3) project-local imports
(e.g., "github.com/devfile/devworkspace-operator/apis/controller/v1alpha1" as
controllerv1alpha1 and
"github.com/devfile/devworkspace-operator/pkg/constants"); insert single blank
lines between these groups and then run 'make fmt' to apply formatting.

In `@webhook/workspace/handler/validate_test.go`:
- Around line 105-124: The test currently asserts a ServiceConflictError when
validateEndpoints (on WebhookHandler) is called with a workspace and a
deletingWorkspace (created via setupWorkspace) that has DeletionTimestamp set;
update the test so it reflects webhook behavior that ignores
deletion-timestamped workspaces: call handler.validateEndpoints(context.TODO(),
workspace) and assert no error (i.e., expect nil) instead of asserting
Error/ErrorAs for *solvers.ServiceConflictError, and remove or replace the
subsequent checks for conflictErr.EndpointName/WorkspaceName accordingly so the
test verifies that deletion-timestamped workspaces do not cause conflicts.
- Around line 16-31: Reorder the import block in the validate_test.go file into
three blank-line-separated groups: (1) standard library imports (context, os,
path/filepath, testing), (2) third-party and Kubernetes imports
(github.com/stretchr/testify/assert, sigs.k8s.io/... , k8s.io/... etc.), and (3)
project-local imports (github.com/devfile/... and your controller packages),
making sure each package stays in its respective group; after rearranging, run
make fmt to apply formatting.

In `@webhook/workspace/handler/validate.go`:
- Around line 81-84: validateEndpoints currently returns raw errors from
h.Client.List which are being appended to devfileErrors and treated as user
validation failures in ValidateDevfile; change validateEndpoints signature to
return (*solvers.ServiceConflictError, error) so real validation conflicts come
back as the typed value and infrastructure/API errors flow via the error return,
update validateEndpoints to return (nil, err) for h.Client.List failures and
(conflictErr, nil) for validation failures, then in ValidateDevfile (and the
other call site around lines 109-112) check the error return first and convert
infrastructure errors into admission.Errored(http.StatusBadRequest, err) (or
propagate the error) instead of appending to devfileErrors, only append
conflictErr.Error() to devfileErrors when the typed conflict value is returned.
- Around line 114-130: The validation loop currently only skips the same
workspace by UID but still inspects workspaces that are being deleted; modify
the loop that iterates workspaceList.Items (and the check around otherWorkspace)
to also skip any otherWorkspace with a non-nil DeletionTimestamp (i.e., treat
terminating workspaces as excluded from discoverable endpoint conflict checks),
so that discoverableEndpoints lookup and potential return of
solvers.ServiceConflictError only considers non-terminating workspaces.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 981c002a-3f92-488e-8077-9057055e9194

📥 Commits

Reviewing files that changed from the base of the PR and between e0ed8d2 and 7a5ff10.

📒 Files selected for processing (12)
  • controllers/controller/devworkspacerouting/devworkspacerouting_controller.go
  • controllers/controller/devworkspacerouting/solvers/basic_solver.go
  • controllers/controller/devworkspacerouting/solvers/cluster_solver.go
  • controllers/controller/devworkspacerouting/solvers/common.go
  • controllers/controller/devworkspacerouting/solvers/common_test.go
  • controllers/controller/devworkspacerouting/solvers/errors.go
  • controllers/controller/devworkspacerouting/solvers/solver.go
  • controllers/workspace/suite_test.go
  • pkg/webhook/cluster_roles.go
  • webhook/workspace/handler/testdata/test-devworkspace.yaml
  • webhook/workspace/handler/validate.go
  • webhook/workspace/handler/validate_test.go

Comment thread controllers/controller/devworkspacerouting/solvers/common_test.go
Comment thread webhook/workspace/handler/validate_test.go
Comment thread webhook/workspace/handler/validate_test.go
Comment thread webhook/workspace/handler/validate.go Outdated
Comment thread webhook/workspace/handler/validate.go Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@webhook/workspace/handler/validate_test.go`:
- Line 1: Update the copyright header in
webhook/workspace/handler/validate_test.go by changing the year range string "//
Copyright (c) 2019-2025 Red Hat, Inc." to the current-year range "// Copyright
(c) 2019-2026 Red Hat, Inc."; locate and replace that exact header line at the
top of the file so it matches the required format used across Go sources.
- Line 58: The test currently ignores the error from dwv2.AddToScheme(scheme);
change this to explicitly assert success by calling assert.NoError(t,
dwv2.AddToScheme(scheme)) so the scheme initialization failure surfaces in the
test; locate the call to dwv2.AddToScheme in validate_test.go (the variable
scheme) and replace the `_ =` ignoring pattern with the assert.NoError check
(using the existing testify/assert import).

In `@webhook/workspace/handler/validate.go`:
- Around line 24-29: Reorder the import block in validate.go so imports follow
Go grouping: first any standard-library packages (none shown here), then a blank
line, then third-party and Kubernetes imports together (e.g.,
"github.com/devfile/api/v2/..." packages and
"sigs.k8s.io/controller-runtime/..." client and admission), then a blank line,
and finally project-local imports (e.g.,
"github.com/devfile/devworkspace-operator/apis/controller/v1alpha1" and
"github.com/devfile/devworkspace-operator/controllers/controller/devworkspacerouting/solvers");
ensure there are blank lines separating these three groups and keep the existing
import identifiers (dwv2, devfilevalidation, v1alpha1, solvers, client,
admission) intact.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 13233f4a-6817-4e7f-a346-91250ddebbe0

📥 Commits

Reviewing files that changed from the base of the PR and between 7a5ff10 and d899dfb.

📒 Files selected for processing (4)
  • .gitignore
  • controllers/controller/devworkspacerouting/solvers/common_test.go
  • webhook/workspace/handler/validate.go
  • webhook/workspace/handler/validate_test.go
✅ Files skipped from review due to trivial changes (1)
  • .gitignore
🚧 Files skipped from review as they are similar to previous changes (1)
  • controllers/controller/devworkspacerouting/solvers/common_test.go

Comment thread webhook/workspace/handler/validate_test.go Outdated
Comment thread webhook/workspace/handler/validate_test.go
Comment thread webhook/workspace/handler/validate.go
@openshift-ci openshift-ci Bot added the lgtm label May 19, 2026
@openshift-ci

openshift-ci Bot commented May 19, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: akurinnoy, rohanKanojia, tolusha
Once this PR has been reviewed and has the lgtm label, please assign dkwon17 for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@tolusha

tolusha commented Jun 26, 2026 •

Copy link
Copy Markdown
Contributor

/che-ai-assistant ok-pr-readiness

Review is complete. Please check the review comments below.

@tolusha

tolusha commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

PR Readiness Assessment: PR #1521 — fix: identical endpoint name conflicts

Repository: devfile/devworkspace-operator
Linked Issue: eclipse-che/che#23231 — Dev Workspace Controller Loop with Identical Endpoint Names on DevWorkspace


# Criterion Verdict Notes
1 Problem Statement PASS PR body and linked issue clearly describe the bug: workspaces with identical discoverable endpoint names cause controller to loop and workspaces get stuck on "Preparing Service"
2 Reproduction Steps PASS Linked issue provides sample devfile and clear steps. PR body includes comprehensive test scenarios with exact commands and YAML manifests for both same-namespace conflict and cross-namespace isolation
3 Expected Behavior After Fix PASS Clear acceptance criteria: same-namespace conflicts should be rejected by webhook with specific error message; cross-namespace workspaces with same endpoint names should run successfully
4 Scope of Changes PASS 13 files changed with focused scope: controller conflict detection, webhook validation, and comprehensive test coverage. Changes are cohesive and well-explained
5 Test Evidence PASS Extensive manual testing instructions with exact commands and expected outputs. New unit tests added in common_test.go and validate_test.go. CodeRabbit confirms extensive test coverage
6 Deployment & Verification Notes PASS Detailed verification steps with specific oc/kubectl commands, expected webhook denial messages, and service verification across namespaces. E2E test checklist included

Overall: READY


Missing Information

None — this PR is exceptionally well-documented.

What's Good

  • Comprehensive test plan: Includes two distinct test scenarios (same-namespace conflict detection and cross-namespace isolation) with complete step-by-step commands
  • Clear problem statement: Both PR description and linked issue explain the controller loop bug with screenshots and environment details
  • Well-defined expected behavior: Explicit acceptance criteria for both conflict and non-conflict cases, including exact error messages
  • Excellent reproducibility: Sample devfiles, exact YAML manifests, and verification commands provided
  • Appropriate scope: Changes are focused on conflict detection logic, webhook validation, and corresponding tests
  • Strong test coverage: Both unit tests (added in the diff) and detailed manual testing instructions
  • Cross-referenced documentation: Links to external issue for full historical context

Validate normalized discoverable endpoint names at admission and reconciliation while preserving update gating. Protect routing Services with fresh ownership checks and guarded writes, preserve owned Service recovery, correct certificate mounts and workspace names, and retain the existing solver interface.

Signed-off-by: Oleksii Kurinnyi <okurinny@redhat.com>
Assisted-by: Codex
Keep canonical endpoint names unchanged without allocating, and normalize other names in one pass while preserving the existing naming behavior.

Signed-off-by: Oleksii Kurinnyi <okurinny@redhat.com>
Assisted-by: Codex
Register a native cache field index and query unique incoming discoverable names within the namespace. Preserve normal object copies, update gating, self exclusion, and conflict behavior; document the index memory and update cost.

Signed-off-by: Oleksii Kurinnyi <okurinny@redhat.com>
Assisted-by: Codex
@akurinnoy
akurinnoy marked this pull request as draft October 8, 2026 10:59
@akurinnoy
akurinnoy force-pushed the identical-endpoint-name branch from d899dfb to 4d93c08 Compare October 8, 2026 11:05
@openshift-ci openshift-ci Bot removed the lgtm label Oct 8, 2026
@openshift-ci

openshift-ci Bot commented Oct 8, 2026

Copy link
Copy Markdown

New changes are detected. LGTM label has been removed.

@codecov

codecov Bot commented Oct 8, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 80.40201% with 39 lines in your changes missing coverage. Please review.
✅ Project coverage is 42.74%. Comparing base (3526ad3) to head (4d93c08).
⚠️ Report is 10 commits behind head on main.

Files with missing lines Patch % Lines
pkg/webhook/cluster_roles.go 0.00% 12 Missing ⚠️
...roller/devworkspacerouting/solvers/basic_solver.go 0.00% 7 Missing ⚠️
pkg/common/naming.go 77.27% 5 Missing ⚠️
...s/controller/devworkspacerouting/solvers/solver.go 0.00% 4 Missing ⚠️
pkg/provision/sync/service.go 0.00% 4 Missing ⚠️
...workspacerouting/devworkspacerouting_controller.go 87.50% 2 Missing and 1 partial ⚠️
...s/controller/devworkspacerouting/solvers/common.go 92.30% 1 Missing and 1 partial ⚠️
...s/controller/devworkspacerouting/solvers/errors.go 0.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1521      +/-   ##
==========================================
+ Coverage   40.45%   42.74%   +2.29%     
==========================================
  Files         174      177       +3     
  Lines       15949    13321    -2628     
==========================================
- Hits         6452     5694     -758     
+ Misses       9096     7192    -1904     
- Partials      401      435      +34     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Dev Workspace Controller Loop with Identical Endpoint Names on DevWorkspace

4 participants